//
//  WaveView.m
//  WaveDemo
//
//  Created by tom on 15/11/26.
//  Copyright © 2015年 azhuoinfo. All rights reserved.
//

#import "WaveView.h"
#import "AppDelegate.h"
#import "heartutil.h"
#import "h.h"

static WaveView * tjj_waveView = nil;
static dispatch_queue_t queueCompareHeart = nil;

#define WNIDTH 40

static int instantBeat = 0;
static int meanBeat = 0;
static int numberOfShowAverage = 0;
static float resrespirate = 0;
static float hrv = 0;
static int muscleFatigue = 0;
static float muscleStrength = 0;
static float headAlpha = 0;
static float headTheta = 0;
static float headAttention = 0;
static float headBeta = 0;
static float headGamma = 0;
static float headRelaxation = 0;


@interface WaveView ()
{
    BOOL isPonintedded;
    BOOL isCountHead;
    BOOL isCounting;
}
@property (nonatomic,strong) NSMutableArray * values;
@property (nonatomic,strong) NSMutableArray * valuesHead;

@property (nonatomic,strong) NSMutableArray * valuesTemp;
@property (nonatomic,strong) NSMutableArray * valueHearts;
@property (nonatomic,strong) NSMutableArray * tempX;
@property (nonatomic,strong) NSMutableArray * tempY;
@property (nonatomic,strong) NSMutableArray * R_index;

@end

@implementation WaveView

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.backgroundColor = [UIColor clearColor];
    }
    return self;
}

- (id)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor clearColor];
        isPonintedded = NO;
        isCountHead = NO;
        isCounting = NO;
        self.valueHearts = [[NSMutableArray alloc] initWithCapacity:0];
        self.values = [[NSMutableArray alloc] initWithCapacity:0];
        self.valuesHead = [[NSMutableArray alloc] initWithCapacity:0];
        self.valuesTemp = [[NSMutableArray alloc] initWithCapacity:0];
        for (int i = 0; i < 1250; i++)
        {
            [self.valuesTemp addObject:@(0)];
            [self.values addObject:@(0)];
        }
        self.R_index = [[NSMutableArray alloc] initWithCapacity:0];
        queueCompareHeart = dispatch_queue_create("com.heart.compareHeart", DISPATCH_QUEUE_SERIAL);
        
        [self updateUI];
        self.addDataTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(updataMonitorNew) userInfo:nil repeats:YES];
    }
    return self;
}

+ (WaveView *)sharingWaveViewWithFrame:(CGRect)frame
{
    static dispatch_once_t once;
    if (tjj_waveView == nil)
    {
        dispatch_once(&once, ^{
            tjj_waveView = [[WaveView alloc] initWithFrame:frame];
        });
    }
    return tjj_waveView;
}

-(void)updataMonitorNew
{
    AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
    [self.valueHearts addObjectsFromArray:delegate.MonitorAry];
    [self.valuesTemp addObjectsFromArray:delegate.MonitorAry];
    NSInteger indext = self.valuesTemp.count;
    if([delegate.type isEqualToString:@"3"])
    {
        if (indext >= kMAX_HORIZINTAL_POINTS) {
        [self.valuesTemp removeObjectsInRange:NSMakeRange(0,indext-kMAX_HORIZINTAL_POINTS)];
        NSInteger sum = self.valuesTemp.count;
        float * datain=(float *) calloc(sum,sizeof(float));
        float * dataout=(float *) calloc(sum,sizeof(float));

        for (int i = 0; i<sum; i++) {
            datain[i] = [[self.valuesTemp objectAtIndex:i] floatValue];
        }
        float * constantA=(float *) calloc(6,sizeof(float));
        float * constantB=(float *) calloc(6,sizeof(float));
        constantA[0]=1.000000000000000;
        constantA[1]=-2.692610987017435;
        constantA[2]=2.867399109111390;
        constantA[3]=-1.403484671368141;
        constantA[4]=0.264454816443504;

        constantB[0]=0.514246848996279;
        constantB[1]=-2.056987395985118;
        constantB[2]=3.085481093977677;
        constantB[3]=-2.056987395985118;
        constantB[4]=0.514246848996279;
        
        self.values =[self filternewNumber:datain andLength:sum andB:constantB andA:constantA andOut:dataout];
        }
        else
        {
        }
    }
    else
    {
        [self.values addObjectsFromArray:delegate.MonitorAry];
    }
 
    [delegate.MonitorAry removeAllObjects];

    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.values.count >= kMAX_HORIZINTAL_POINTS)
        {
            NSInteger indexta = self.values.count;
            [self.values removeObjectsInRange:NSMakeRange(0,indexta-kMAX_HORIZINTAL_POINTS)];
        }
        [self setNeedsDisplay];
    });
    
    if ([delegate.type isEqualToString:@"1"] && !delegate.isHeading)
    {
        delegate.isHeading = YES;
        if (!isCountHead)
        {
            isCountHead = YES;
            dispatch_async(queueCompareHeart, ^{
                [self CompareHead];
            });
        }
        else
        {
            delegate.isHeading = NO;
        }
    }
    else if ([delegate.type isEqualToString:@"2"] && !delegate.isHearting)
    {
        delegate.isHearting = YES;
        dispatch_async(queueCompareHeart, ^{//开启子线程
            [self CompareHeart];
        });
    }
    else if ([delegate.type isEqualToString:@"3"])
    {
        dispatch_async(queueCompareHeart, ^{//开启子线程
            [self CompareMuscle];
        });
    }
    else
    {
        //其他未知错误进入的
    }
    
}


- (NSMutableArray *)filternewNumber:(float *)epoch andLength:(int)m andB:(float *)bn andA:(float *)an andOut:(float *)out{
    int j;
    out[0]=epoch[0]*bn[0];
    out[1]=epoch[1]*bn[0]+epoch[0]*bn[1]-out[0]*an[1];
    out[2]=epoch[2]*bn[0]+epoch[1]*bn[1]+epoch[0]*bn[2]-out[1]*an[1]-out[0]*an[2];
    out[3]=epoch[3]*bn[0]+epoch[2]*bn[1]+epoch[1]*bn[2]+epoch[0]*bn[3]-out[2]*an[1]-out[1]*an[2]-out[0]*an[3];
    out[4]=epoch[4]*bn[0]+epoch[3]*bn[1]+epoch[2]*bn[2]+epoch[1]*bn[3]+epoch[0]*bn[4]-out[3]*an[1]-out[2]*an[2]-out[1]*an[3]-out[0]*an[4];
    out[5]=epoch[5]*bn[0]+epoch[4]*bn[1]+epoch[3]*bn[2]+epoch[2]*bn[3]+epoch[1]*bn[4]+epoch[0]*bn[5]-out[4]*an[1]-out[3]*an[2]-out[2]*an[3]-out[1]*an[4]-out[0]*an[5];
    
    for(j=6;j<m;j++){
        out[j]=epoch[j]*bn[0]+epoch[j-1]*bn[1]+epoch[j-2]*bn[2]+epoch[j-3]*bn[3]+epoch[j-4]*bn[4]+epoch[j-5]*bn[5]+epoch[j-6]*bn[6]-out[j-1]*an[1]-out[j-2]*an[2]-out[j-3]*an[3]-out[j-4]*an[4]-out[j-5]*an[5]-out[j-6]*an[6];
    }
    
    NSMutableArray * nsArray = [[NSMutableArray alloc] initWithCapacity:0];
    for (int i = 0 ; i < m ; i++)
    {
        [nsArray addObject:@(out[i])];
    }
    return nsArray;
}


- (void)updateUI
{
    dispatch_async(dispatch_get_main_queue(), ^{
        [self setNeedsDisplay];
    });
}

- (void)CompareHeart
{
    
    if (self.R_index.count > 0)
    {
        [self.R_index removeAllObjects];
    }
    int r_num;  //当前检测到的R波个数
    int len = (int)self.valueHearts.count;//数据的个数
    if (len >= kMAX_HORIZINTAL_POINTS*2)
    {
        [self.valueHearts removeObjectsInRange:NSMakeRange(0, len - kMAX_HORIZINTAL_POINTS*2)];
        len = (int)self.valueHearts.count;
        isPonintedded = YES;
    }
    //C++ 创建一个double类型的数组
    double * valuesDouble= (double * )calloc(len,sizeof(double));
    
    for (int i =0; i<len; i++)
    {
        valuesDouble[i] = [self.valueHearts[i] doubleValue];
    }

    int * R_index = (int * )calloc(100,sizeof(int));
    
    if (len == kMAX_HORIZINTAL_POINTS*2 && isPonintedded)
    {
        r_num = QRSdetection(valuesDouble, R_index,len,100);
        if (numberOfShowAverage >= NUMBER_UPUI || (meanBeat < 40) || (meanBeat > 160))
        {//10秒钟计算一次平均速率
            meanBeat = (int)round((r_num/10.0)*60);
            if (numberOfShowAverage >= NUMBER_UPUI)
            {
                numberOfShowAverage = 0;//计时器归零
            }
        }
        else
        {
            numberOfShowAverage ++;//计时器加1
        }
        if (r_num > 1 && (R_index[r_num-1]-R_index[r_num-2]>0))
        {
            instantBeat = (int)round(60/((R_index[r_num-1]-R_index[r_num-2])*0.004));
        }
        else
        {
            instantBeat = 0;
        }
        isPonintedded = false;

        NSInteger sum = self.values.count;
        float * datain=(float *) calloc(sum,sizeof(float));
        
        for (int i = 0; i<sum; i++) {//赋值
            datain[i] = [[self.values objectAtIndex:i] floatValue];
        }
        hrv = HRV_SDNN(R_index, r_num);//HRV
        
        resrespirate = respiration2(datain, sum, R_index, r_num, CONSTANTFS);//最终使用方法
        
//        if (resrespirate > 0)
//        {
        
            free(datain);
            datain = NULL;
            r_num = 0;//计数器清零
            free(valuesDouble);
            valuesDouble = NULL;
            free(R_index);
            R_index = NULL;
            //添加 字典，将平均心率和瞬时心率的值通过key值设置传递
            NSDictionary *dictionaryOfHeart =[[NSDictionary alloc] initWithObjectsAndKeys:@(instantBeat),@"Ontime",@(meanBeat),@"Average", @(hrv),@"hrv",@(resrespirate),@"resrespiration", nil];
            NSNotification *notificationUpdateLabel =[NSNotification notificationWithName:_NOTIFICATION_UPDATE_LABEL object:nil userInfo:dictionaryOfHeart];
            [[NSNotificationCenter defaultCenter] postNotification:notificationUpdateLabel];
//        }
//        else
//        {
//            free(datain);
//            datain = NULL;
//            r_num = 0;//计数器清零
//            free(valuesDouble);
//            valuesDouble = NULL;
//            free(R_index);
//            R_index = NULL;
//            //添加 字典，将平均心率和瞬时心率的值通过key值设置传递
//            NSDictionary *dictionaryOfHeart =[[NSDictionary alloc] initWithObjectsAndKeys:@(instantBeat),@"Ontime",@(meanBeat),@"Average", @(hrv),@"hrv",@(resrespirate),@"resrespiration", nil];
//            NSNotification *notificationUpdateLabel =[NSNotification notificationWithName:_NOTIFICATION_UPDATE_LABEL object:nil userInfo:dictionaryOfHeart];
//            [[NSNotificationCenter defaultCenter] postNotification:notificationUpdateLabel];
//        }
    }
    else
    {
        AppDelegate * delegate = [[UIApplication sharedApplication] delegate];
        delegate.isHearting = NO;
        
        r_num = 0;//计数器清零
        free(valuesDouble);
        valuesDouble = NULL;
        free(R_index);
        R_index = NULL;
    }
}


- (void)CompareMuscle
{
    NSInteger sum = self.values.count;
    float * datain=(float *) calloc(sum,sizeof(float));
    
    for (int i = 0; i<sum; i++) {//赋值
        datain[i] = [[self.values objectAtIndex:i] floatValue];
    }
    
    muscleStrength = muscle_strength(datain, sum);
    if (muscleStrength < 0) {
        muscleStrength *= -1;
    }
    muscleFatigue = muscle_fatigue(datain, sum, CONSTANTFS);
    
    free(datain);//释放内存空间
    NSDictionary *dictionaryOfHeart =[[NSDictionary alloc] initWithObjectsAndKeys:@(muscleFatigue),@"fatigue",@(muscleStrength),@"strength", nil];
    NSNotification *notificationUpdateLabel =[NSNotification notificationWithName:_NOTIFICATION_UPDATE_LABEL object:nil userInfo:dictionaryOfHeart];
    [[NSNotificationCenter defaultCenter] postNotification:notificationUpdateLabel];
}


- (void)CompareHead
{
    AppDelegate * delegate = [[UIApplication sharedApplication] delegate];
    if (!isCounting)
    {
        isCounting = YES;
        self.valuesHead = self.values;
        float * datain;
        if (self.valuesHead.count >= 1250)
        {
            datain=(float *) calloc(1250,sizeof(float));
            [self.valuesHead removeObjectsInRange:NSMakeRange(0, self.valuesHead.count - 1250)];
            if (self.valuesHead.count >= 1250) {
                for (int i = 0; i<kMAX_HORIZINTAL_POINTS; i++) {
                    if (i >= self.valuesHead.count) {
                        isCountHead = NO;
                        isCounting = NO;
                        delegate.isHeading = NO;
                        break;
                    }
                    datain[i] = [[self.valuesHead objectAtIndex:i] floatValue];
                }
        
                if (isCounting) {
                    float *fdata = (float *) calloc(9,sizeof(float));
                    fdatacacu(fdata, 1250, datain);
                    headAlpha = fdata[4];//alpha
                    headTheta = fdata[7];
                    headAttention = fdata[0];
                    headBeta = fdata[5];
                    headGamma = fdata[8];
                    headRelaxation = fdata[1];
                    
                    NSDictionary *dictionaryOfHeart =[[NSDictionary alloc] initWithObjectsAndKeys:@(headAlpha),@"alpha",@(headTheta),@"theta", @(headAttention),@"attention",@(headBeta),@"beta", @(headGamma),@"gamma",@(headRelaxation),@"relaxation", nil];
                    NSNotification *notificationUpdateLabel =[NSNotification notificationWithName:_NOTIFICATION_UPDATE_LABEL object:nil userInfo:dictionaryOfHeart];
                    [[NSNotificationCenter defaultCenter] postNotification:notificationUpdateLabel];
                    isCountHead = NO;
                    isCounting = NO;
                }
                
            }
            else
            {
                isCountHead = NO;
                isCounting = NO;
                delegate.isHeading = NO;
            }
    }
    else
    {
        delegate.isHeading = NO;
        isCountHead = NO;
        isCounting = NO;
    }
    }
    else
    {
    }
}

- (void)drawRect:(CGRect)rect {
    [self drawCurve];
}

- (void)drawCurve
{
    if (self.values.count == 0) {
        return;
    }
    CGFloat curveLineWidth = 0.8;
    CGContextRef currentContext = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(currentContext, curveLineWidth);
    AppDelegate *delegate = [[UIApplication sharedApplication]delegate];
    CGContextSetStrokeColorWithColor(currentContext, delegate.currentColor.CGColor);//画线的颜色
    CGFloat halfH = SCREEN_WIDTH/2.0;
    CGFloat max = (CGFloat)delegate.scope*2;
    CGFloat width = SCREEN_HEIGHT*1.0;//屏幕高度，画图板的宽度 ，如5S，568.
    CGFloat yn = (CGFloat)((1+[self.values[0] longLongValue]/max)*halfH);
    CGContextMoveToPoint(currentContext,0,yn);//移除第一个
    //Y坐标轴平移 （从上边往下边）（状态栏为上）
    for (int i = 1; i != self.values.count; ++i) {
        CGFloat x = i/(CGFloat)kMAX_HORIZINTAL_POINTS*width;//原来
        CGFloat y = (CGFloat)((1+[self.values[i] longLongValue]/max)*halfH);//参考Android的(number)
        if (i <= kMAX_HORIZINTAL_POINTS) {
            CGContextAddLineToPoint(currentContext,x,y);
        } else {
            CGContextMoveToPoint(currentContext,x,y);
        }
    }
    //X坐标轴平移(从左边向右边)
    //    for (int i = 1; i != self.currentPointsCount; ++ i) {
    //        if (self.points[i - 1].x < self.points[i].x) {
    //            CGContextAddLineToPoint(currentContext, self.points[i].x, self.points[i].y);
    //        } else {
    //            CGContextMoveToPoint(currentContext, self.points[i].x, self.points[i].y);
    //        }
    //    }
    CGContextStrokePath(UIGraphicsGetCurrentContext());
}


- (NSNumber *)overfiltering:(NSNumber *)number
{
    [self.tempX addObject:number];//添加一个新数据
    [self.tempX removeObjectAtIndex:0];//移除第一个数据
    NSInteger n = self.tempX.count-1;//n的坐标。
    double newNumber = ([self.tempY[n-1] doubleValue] +0.2925*([self.tempX[n] doubleValue]-[self.tempX[n-5] doubleValue]))/1.25;//newpt = (y.get(n-1)+0.2925*(x.get(n)-x.get(n-5)))/1.25
    [self.tempY addObject:@(newNumber)];
    [self.tempY removeObjectAtIndex:0];//移除第一个数
    return @(newNumber);
}


- (void)removeObserver:(id)observer
{
    NSLog(@"====%@ remove===", [observer class]);
}
//#pragma mark -
//#pragma mark 销毁
//-(void)dealloc
//{
//    
//    NSNotification * notificationUpdataDataOne =[NSNotification notificationWithName:_NOTIFICATION_UPDATE_MONITOR object:nil userInfo:nil];
//    [[NSNotificationCenter defaultCenter] removeObserver:self name:notificationUpdataDataOne object:nil];
////     postNotification:notificationUpdataDataOne];
//}
@end
